home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / util / tracktls / part01 next >
Encoding:
Internet Message Format  |  1990-01-20  |  54.5 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i029: Trackutils - utilities to allocate and copy disk tracks, Part01/02
  5. Message-ID: <11069@xanth.cs.odu.edu>
  6. Date: 20 Jan 90 15:37:27 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: Eddy Carroll <ECARROLL%vax1.tcd.ie@CUNYVM.CUNY.EDU>
  9. Lines: 1740
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11.  
  12. Submitted-by: Eddy Carroll <ECARROLL%vax1.tcd.ie@CUNYVM.CUNY.EDU>
  13. Posting-number: Volume 90, Issue 029
  14. Archive-name: util/trackutils/part01
  15.  
  16. This archive contains two utilities, TCopy and TFile. I've included them
  17. together because they complement each other quite well.
  18.  
  19. TCopy is a utility for copying one or more tracks from one disk to another.
  20. It also has facilities for automatically mounting RAD: which makes it ideal
  21. for use during bootup (mount RAD: and copy stuff into it all in one go).
  22.  
  23. TFile reserves a range of tracks on a disk, so that AmigaDOS can't overwrite
  24. them accidentally. This is particularly useful for protecting some data
  25. that has been TCopy'd, but it has other applications also.
  26.  
  27. Source is contained in the src subdirectory within the zoo archive.
  28.  
  29. Regards,
  30. Eddy Carroll                                          ecarroll@vax1.tcd.ie
  31.  
  32.  
  33. #!/bin/sh
  34. # This is a shell archive.  Remove anything before this line, then unpack
  35. # it by saving it into a file and typing "sh file".  To overwrite existing
  36. # files, type "sh file -c".  You can also feed this as standard input via
  37. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  38. # will see the following message at the end:
  39. #        "End of archive 1 (of 2)."
  40. # Contents:  src src/dosheaders.h src/makefile src/system.h src/tcopy.c
  41. #   src/tiny.a tcopy.doc tfile.doc
  42. # Wrapped by tadguy@xanth on Sat Jan 20 10:37:16 1990
  43. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  44. if test ! -d 'src' ; then
  45.     echo shar: Creating directory \"'src'\"
  46.     mkdir 'src'
  47. fi
  48. if test -f 'src/dosheaders.h' -a "${1}" != "-c" ; then 
  49.   echo shar: Will not clobber existing file \"'src/dosheaders.h'\"
  50. else
  51. echo shar: Extracting \"'src/dosheaders.h'\" \(2177 characters\)
  52. sed "s/^X//" >'src/dosheaders.h' <<'END_OF_FILE'
  53. X/*
  54. X *        DOSHEADER.H
  55. X *
  56. X *        This file contains a few structures which map out the main
  57. X *        AmigaDOS disk structures (root block, directory block etc.)
  58. X *        These are valid for both the old and new filing systems.
  59. X *
  60. X *        Taken from Betty Clay's article on the differences between the
  61. X *        old FS and new FS under 1.3, in Transactor UK, V1.6, May 1989, and
  62. X *        from the original AmigaDOS Technical Reference manual.
  63. X */
  64. X
  65. X#define BTOC(x)        ((void *)((long)(x)<<2))        /* BPTR to C pointer    */
  66. X#define CTOB(x)        ((ULONG) ((long)(x)>>2))        /* C pointer to BPTR    */
  67. X
  68. X/*
  69. X *        Disk block types
  70. X */
  71. X
  72. X#define Type_Short        0x02
  73. X#define Type_Data        0x08
  74. X#define Type_List        0x10
  75. X
  76. X#define SecType_File    0xfffffffd
  77. X#define SecType_Root    0x01
  78. X#define SecType_UserDir    0x02
  79. X
  80. Xstruct RootBlock {
  81. X    LONG    Type;
  82. X    ULONG    OwnKey;
  83. X    ULONG    SeqNum;
  84. X    ULONG    HtSize;
  85. X    ULONG    Nothing1;
  86. X    ULONG    Checksum;
  87. X    ULONG    HashTable[72];
  88. X    LONG    BitmapFlag;
  89. X    ULONG    BitmapKeys[25];
  90. X    ULONG    BitmapExtend;
  91. X    ULONG    DirAltered[3];
  92. X    char    Name[40];
  93. X    ULONG    DiskAltered[3];
  94. X    ULONG    DiskMade[3];
  95. X    ULONG    Nothing2;
  96. X    ULONG    Nothing3;
  97. X    ULONG    Nothing4;
  98. X    LONG    SecondaryType;
  99. X};
  100. X
  101. Xstruct UserDirectoryBlock {
  102. X    LONG    Type;
  103. X    ULONG    OwnKey;
  104. X    ULONG    Spare1;
  105. X    ULONG    Spare2;
  106. X    ULONG    Spare3;
  107. X    LONG    Checksum;
  108. X    ULONG    HashTable[72];
  109. X    LONG    Spare4;
  110. X    LONG    Spare5;
  111. X    ULONG    Protection;
  112. X    LONG    Spare6;
  113. X    char    Comment[92];
  114. X    ULONG    Created[3];
  115. X    char    DirName[36];
  116. X    LONG    Spare7[7];
  117. X    ULONG    HashChain;
  118. X    ULONG    Parent;
  119. X    ULONG    Spare8;
  120. X    LONG    SecondaryType;
  121. X};
  122. X
  123. Xstruct FileHeaderBlock {
  124. X    LONG    Type;
  125. X    ULONG    OwnKey;
  126. X    ULONG    HighSeq;
  127. X    ULONG    DataSize;
  128. X    ULONG    FirstBlock;
  129. X    LONG    Checksum;
  130. X    ULONG    DataBlocks[72];
  131. X    ULONG    Spare1;
  132. X    ULONG    Spare2;
  133. X    ULONG    Protect;
  134. X    ULONG    FileSize;
  135. X    char    Comment[92];
  136. X    ULONG    Date[3];
  137. X    char    FileName[36];
  138. X    ULONG    Spare3[7];
  139. X    ULONG    HashChain;
  140. X    ULONG    Parent;
  141. X    ULONG    Extension;
  142. X    LONG    SecondaryType;
  143. X};
  144. X
  145. Xstruct FileListBlock {
  146. X    LONG    Type;
  147. X    ULONG    OwnKey;
  148. X    ULONG    BlockCount;
  149. X    ULONG    DataSize;
  150. X    ULONG    FirstBlock;
  151. X    LONG    Checksum;
  152. X    ULONG    DataBlocks[72];
  153. X    ULONG    Unused[47];
  154. X    ULONG    Parent;
  155. X    ULONG    Extension;
  156. X    LONG    SecondaryType;
  157. X};
  158. X
  159. Xstruct DataBlock {            /* Old Filing System only */
  160. X    LONG    Type;
  161. X    ULONG    Header;
  162. X    ULONG    SeqNum;
  163. X    ULONG    DataSize;
  164. X    ULONG    NextData;
  165. X    LONG    Checksum;
  166. X    ULONG    Data[122];
  167. X};
  168. END_OF_FILE
  169. if test 2177 -ne `wc -c <'src/dosheaders.h'`; then
  170.     echo shar: \"'src/dosheaders.h'\" unpacked with wrong size!
  171. fi
  172. # end of 'src/dosheaders.h'
  173. fi
  174. if test -f 'src/makefile' -a "${1}" != "-c" ; then 
  175.   echo shar: Will not clobber existing file \"'src/makefile'\"
  176. else
  177. echo shar: Extracting \"'src/makefile'\" \(1005 characters\)
  178. sed "s/^X//" >'src/makefile' <<'END_OF_FILE'
  179. X#
  180. X# Lattice LKM makefile, for Lattice C V5.04
  181. X#
  182. X# Tcopy, Tfile (C) Copyright Eddy Carroll, January 1990
  183. X#
  184. X
  185. XSYMBOLS = RAMBO
  186. XCFLAGS    = -cusq -ms -v -j88i -D$(SYMBOLS) # -D3
  187. X#                                         # Use -D2 if compiling for TraceBack
  188. XOPT     = -O    # Optimisation
  189. X#BFLAGS    = sc sd map ram:map addsym
  190. XBFLAGS    = sc sd map ram:map nd
  191. XASM        = lc:asm
  192. XSTART    = tiny.o
  193. X#START    = lib:catch.o
  194. XLIBS    = lib:lc.lib lib:amiga.lib
  195. X
  196. X.c.o:
  197. X    lc $(CFLAGS) $(OPT) -Hsystem.sym $*.c
  198. X.a.o:
  199. X    $(ASM) -isys:include/ -u $*.a
  200. X.n.doc:
  201. X    nro >$*.doc -ms:an $*.n
  202. X.h.sym:
  203. X    copy $*.h to ram:t/dummy.c 
  204. X    lc $(CFLAGS) -ph -o$*.sym ram:t/dummy.c
  205. X    delete ram:t/dummy.c
  206. X
  207. X#
  208. X# Makefile dependencies
  209. X#
  210. XOBJS1   = tcopy.o
  211. XOBJS2   = tfile.o
  212. X
  213. Xall: tiny.o tfile tcopy
  214. X
  215. Xtcopy: $(OBJS1)
  216. X    blink from $(START) $(OBJS1) to tcopy $(BFLAGS) lib $(LIBS)
  217. X
  218. Xtfile: $(OBJS2)
  219. X    blink from $(START) $(OBJS2) to tfile $(BFLAGS) lib $(LIBS)
  220. X
  221. Xsystem.sym:        system.h
  222. Xtcopy.o:        tcopy.c        system.sym
  223. Xtfile.o:        tfile.c        system.sym    dosheaders.h
  224. Xtiny.o:            tiny.a
  225. END_OF_FILE
  226. if test 1005 -ne `wc -c <'src/makefile'`; then
  227.     echo shar: \"'src/makefile'\" unpacked with wrong size!
  228. fi
  229. # end of 'src/makefile'
  230. fi
  231. if test -f 'src/system.h' -a "${1}" != "-c" ; then 
  232.   echo shar: Will not clobber existing file \"'src/system.h'\"
  233. else
  234. echo shar: Extracting \"'src/system.h'\" \(361 characters\)
  235. sed "s/^X//" >'src/system.h' <<'END_OF_FILE'
  236. X#include <exec/types.h>
  237. X#include <exec/ports.h>
  238. X#include <exec/io.h>
  239. X#include <exec/memory.h>
  240. X#include <devices/trackdisk.h>
  241. X#include <libraries/dos.h>
  242. X#include <libraries/dosextens.h>
  243. X#include <libraries/filehandler.h>
  244. X#include <proto/exec.h>
  245. X#include <proto/dos.h>
  246. X#include <ctype.h>
  247. X#include <string.h>
  248. X#ifdef RAMBO
  249. X#include <proto/expansion.h>
  250. X#endif RAMBO
  251. END_OF_FILE
  252. if test 361 -ne `wc -c <'src/system.h'`; then
  253.     echo shar: \"'src/system.h'\" unpacked with wrong size!
  254. fi
  255. # end of 'src/system.h'
  256. fi
  257. if test -f 'src/tcopy.c' -a "${1}" != "-c" ; then 
  258.   echo shar: Will not clobber existing file \"'src/tcopy.c'\"
  259. else
  260. echo shar: Extracting \"'src/tcopy.c'\" \(22873 characters\)
  261. sed "s/^X//" >'src/tcopy.c' <<'END_OF_FILE'
  262. X/*
  263. X * TRACKCOPY.C
  264. X *
  265. X * (C) Copyright Eddy Carroll 1989
  266. X *
  267. X * This program allows you to copy a portion of one disk device to a portion
  268. X * of another device which has similar sector and track layout, though may
  269. X * have a different number of cylinders. It is primarily intended to allow
  270. X * a recoverable ram disk like RAD: to be preloaded directly from floppy
  271. X * disk at high speed, a track at a time, instead of having to copy in files
  272. X * manually.
  273. X *
  274. X * Usage: tcopy <srcdevice> <destdevice> <start> <stop> <newstart>
  275. X *
  276. X * The parameters are as follows (example values are in brackets)
  277. X *
  278. X * <srcdevice>    The device to copy from (DF0:)
  279. X * <destdevice>    The device to copy to (RAD:)
  280. X * <start>        The starting cylinder on <srcdevice> (60)
  281. X * <end>        The ending cylinder on <srcdevice> (79)
  282. X * <newstart>    The starting cylinder on <destdevice> (0)
  283. X *
  284. X * For example, supposing you want to setup a disk that you can load into
  285. X * a 264K RAD (equals 24 cylinders of 2 tracks of 11 sectors of 512 bytes).
  286. X * First of all, you setup RAD: manually by mounting it and then copying
  287. X * in the appropriate files. Then you put a blank formatted disk into
  288. X * drive 0 and give the command:
  289. X *
  290. X *         tcopy RAD: DF0: 0 23 56
  291. X *
  292. X * Meaning: Copy cylinders 0-23 of RAD: to cylinders 56-79 of DF0:.
  293. X *
  294. X * You then add enough files to DF0: to make a minimal boot disk, taking care
  295. X * not to add more than (56-40 = 16) cylinders of data (or 176K), since
  296. X * this would cause the data you've just written directly onto the disk
  297. X * to be overwritten. Then put the command:
  298. X *
  299. X *        tcopy DF0: RAD: 56 79 0
  300. X *
  301. X * into your startup-sequence, and when you reboot, RAD: will be reloaded
  302. X * with the appropriate information.
  303. X * ----
  304. X * An additional option may be compiled in by defining the constant
  305. X * RAMBO at compile time. When this is done, tcopy will have
  306. X * some additional options which allow rad: to be automatically mounted
  307. X * and initialised. This is designed to remove the overhead of having
  308. X * to do a MOUNT RAD: in your startup-sequence. When this is the case,
  309. X * the following options may be specified before the rest of the command
  310. X * line. If none are specified, RAD: is not mounted. Defaults are in ().
  311. X *
  312. X *     -v<name>    Sets RAD: volume name to be <name>  ("RAMB0")
  313. X *     -n<name>    Sets RAD: device name to be <name>  ("RAD") (no colon!)
  314. X *     -d<name>    Sets RAD: exec device to be <name>  ("ramdrive.device")
  315. X *       -e<txt>       Echos <txt> to stdout
  316. X *       -a           Always do track copy, even if RAD: already mounted
  317. X *     -f#         Sets flags for OpenDevice() to #    (0)
  318. X *     -m#         Sets BufMemType to #                (1)
  319. X *     -p#         Sets boot priority to #             (-1)
  320. X *     -t#         Sets number of tracks(%) to #       (10)
  321. X *     -u#         Sets unit number of device to be #  (0)
  322. X *
  323. X * (%) Actually the number of cylinders, but people seem to like to think
  324. X *     of them as tracks.
  325. X */
  326. X
  327. X#define TRUE            1
  328. X#define FALSE            0
  329. X#define LASTCHAR(s)        (s[strlen(s)-1])
  330. X
  331. X#ifndef LATTICE_50
  332. X#include "system.h"
  333. X#endif
  334. X
  335. Xextern struct DosLibrary       *DOSBase;
  336. X
  337. Xtypedef struct IORequest       IOREQ;
  338. Xtypedef struct MsgPort         MSGPORT;
  339. Xtypedef struct Process         PROC;
  340. Xtypedef struct StandardPacket  STDPKT;
  341. X
  342. Xvoid inhibit(MSGPORT *devport, int mode);
  343. X/*
  344. X *        Structure representing a disk device
  345. X */
  346. Xtypedef struct {
  347. X    char  *devname;            /* Name of exec device for this disk    */
  348. X    int   isfloppy;            /* True if device is trackdisk.device    */
  349. X    ULONG unit;                /* Unit number of above exec device        */
  350. X    ULONG blocksize;        /* Number of bytes per block            */
  351. X    ULONG blockspertrack;    /* Number of blocks/sectors per track    */
  352. X    ULONG surfaces;            /* Number of tracks per cylinder        */
  353. X    ULONG lowcyl;            /* Starting cylinder of disk on device     */
  354. X    ULONG numcyl;            /* Number of cylinders on this disk        */
  355. X} DISKDEV;
  356. X
  357. X#ifdef RAMBO
  358. X/************************** Declarations for RAMBO **************************/
  359. X
  360. Xstruct ExpansionBase *ExpansionBase;
  361. X
  362. Xchar execname[] = "ramdrive.device";
  363. Xchar dosname[]  = "RAD";
  364. Xchar *volname   = "RAMB0";
  365. Xint bootpri     = -1;
  366. X
  367. X/*
  368. X *        Parameter block for mounting RAD:
  369. X */
  370. Xstruct MountParamBlock {
  371. X    char    *dosname;
  372. X    char    *execname;
  373. X    ULONG    unit;
  374. X    ULONG    flags;
  375. X    ULONG    size;
  376. X    ULONG    blocksize;
  377. X    ULONG    origin;
  378. X    ULONG    surfaces;
  379. X    ULONG    sectorperblock;
  380. X    ULONG    sectorspertrack;
  381. X    ULONG    reserved;
  382. X    ULONG    prealloc;
  383. X    ULONG    interleave;
  384. X    ULONG    lowcyl;
  385. X    ULONG    highcyl;
  386. X    ULONG    numbuffers;
  387. X    ULONG    bufmemtype;
  388. X} mount = {
  389. X    dosname,
  390. X    execname,
  391. X    0,                    /*  2: Unit number                        */
  392. X    0,                    /*  3: OpenDevice() flags                */
  393. X
  394. X    /* This is where the environment block starts */
  395. X    11,                    /*  4: Table upper bound                */
  396. X    512>>2,                /*  5: Number of longwords per block    */
  397. X    0,                    /*  6: Sector origin - unused            */
  398. X    2,                    /*  7: Number of surfaces                */
  399. X    1,                    /*  8: Sectors per block - unused        */
  400. X    11,                    /*  9: Sectors per track                */
  401. X    2,                    /* 10: Reserved blocks - boot block        */
  402. X    0,                    /* 11: Reserved blocks at end            */
  403. X    0,                    /* 12: Interleave                        */
  404. X    0,                    /* 13: Low cylinder                        */
  405. X    10,                    /* 14: High cylinder                    */
  406. X    5                     /* 15: Number of buffers                */
  407. X};
  408. X
  409. X/*********************** End of declarations for RAMBO *********************/
  410. X#endif RAMBO
  411. X
  412. X/*
  413. X *        Global variables
  414. X */
  415. X
  416. Xchar *srcname;                    /* AmigaDos name of source device            */
  417. Xchar *destname;                    /* AmigaDos name of destination device        */
  418. XDISKDEV src[1];                    /* Source disk device                        */
  419. XDISKDEV dest[1];                /* Destination disk device                    */
  420. Xstruct IOStdReq *srcreq;        /* Standard request for source device        */
  421. Xstruct IOStdReq *destreq;        /* Standard request for destination device    */
  422. XMSGPORT *reqport;                /* Message port for replies from devices    */
  423. XMSGPORT *destport;                /* Message port of process of dest. device    */
  424. Xvoid *buffer;                    /* Pointer to data buffer for track r/w        */
  425. Xlong cylsize;                    /* Size in bytes of a single cylinder        */
  426. Xint    srcdevopen;                    /* True if source exec device is open        */
  427. Xint    destdevopen;                /* True if destination device is open        */
  428. Xint inhibited;                    /* True if destination device is inhibited    */
  429. X
  430. X
  431. X/*
  432. X *        print()
  433. X *        -------
  434. X *        Outputs a message to stdout
  435. X */
  436. Xvoid print(char *s)
  437. X{
  438. X    Write(Output(), s, strlen(s));
  439. X}
  440. X#define print2(s1,s2)    (print(s1),print(s2))
  441. X#define print3(s1,s2,s3) (print(s1),print(s2),print(s3))
  442. X
  443. X/*
  444. X *        numtostr()
  445. X *        ----------
  446. X *        Simple little function which returns a pointer to a static string
  447. X *        representation of the passed in number.
  448. X */
  449. Xchar *numtostr(int n)
  450. X{
  451. X    static char s[20];
  452. X    int i = 19;
  453. X
  454. X    s[19] = '\0';
  455. X    if (n)
  456. X        while (n) {
  457. X            s[--i] = '0' + (n % 10);
  458. X            n /= 10;
  459. X        }
  460. X    else
  461. X        s[--i] = '0';
  462. X    return(&s[i]);
  463. X}
  464. X
  465. X
  466. X/*
  467. X *        cleanup()
  468. X *        ---------
  469. X *        Closes all opened resources, and exits with specified error code.
  470. X */
  471. Xvoid cleanup(int code)
  472. X{
  473. X    if (buffer)
  474. X        FreeMem(buffer, cylsize);
  475. X
  476. X    if (srcdevopen) {
  477. X        if (src->isfloppy) {    /* Turn off drive motor if floppy disk */
  478. X            srcreq->io_Command = TD_MOTOR;
  479. X            srcreq->io_Length = 0;
  480. X            DoIO((IOREQ *)srcreq);
  481. X        }
  482. X        CloseDevice((IOREQ *)srcreq);
  483. X    }
  484. X    if (destdevopen) {
  485. X        if (dest->isfloppy) {    /* Turn off drive motor if floppy disk */
  486. X            destreq->io_Command = TD_MOTOR;
  487. X            destreq->io_Length = 0;
  488. X            DoIO((IOREQ *)destreq);
  489. X        }
  490. X        CloseDevice((IOREQ *)destreq);
  491. X    }
  492. X
  493. X    if (inhibited)
  494. X        inhibit(destport, FALSE);
  495. X
  496. X    if (srcreq)
  497. X        DeleteStdIO(srcreq);
  498. X    if (destreq)
  499. X        DeleteStdIO(destreq);
  500. X
  501. X    if (reqport)
  502. X        DeletePort(reqport);
  503. X
  504. X#ifdef RAMBO
  505. X    if (ExpansionBase)
  506. X        CloseLibrary((struct Library *)ExpansionBase);
  507. X#endif RAMBO
  508. X
  509. X    exit(code);
  510. X}
  511. X
  512. X
  513. X/*
  514. X *        chkabort()
  515. X *        ----------
  516. X *        A replacement for Lattice's chkabort(), which doesn't carry all
  517. X *        the extra baggage. If CTRL-C is detected, this function never
  518. X *        returns but instead calls cleanup. Since Lattice's exit() code
  519. X *        may call chkabort(), a check is made to ensure that cleanup()
  520. X *        only gets called once, otherwise there would be a problem if the
  521. X *        user pressed Ctrl-C twice in quick succession.
  522. X */
  523. Xvoid chkabort()
  524. X{
  525. X    static int gotctrlc = FALSE;
  526. X    if (!gotctrlc && (SetSignal(0,0) & SIGBREAKF_CTRL_C)) {
  527. X        gotctrlc = TRUE;
  528. X        print("^C\n");
  529. X        cleanup(20);
  530. X    }
  531. X}
  532. X
  533. X/*
  534. X *        GetVolume()
  535. X *        -----------
  536. X *        This function searches the device list for the named volume, and
  537. X *        fills in the passed DISKDEV structure with information about the
  538. X *        volume. If the named volume is not a device, or is not a disk,
  539. X *        then FALSE is returned. It is not an error to pass in NULL as
  540. X *        a pointer to the DISKDEV structure. In this case, nothing will
  541. X *        be filled in, but TRUE or FALSE will be returned indicating whether
  542. X *        the device is a disk device or not.
  543. X */
  544. Xint GetVolume(char *devname, DISKDEV *dev)
  545. X{
  546. X    struct RootNode *rootnode;
  547. X    struct DosInfo *dosinfo;
  548. X    struct DeviceNode *devnode;
  549. X    struct FileSysStartupMsg *startup;
  550. X    struct DosEnvec *dosenvec;
  551. X    unsigned char *p;
  552. X    int namelen = strlen(devname);
  553. X
  554. X    if (LASTCHAR(devname) != ':')    /* Device names must end with ':' */
  555. X        return (FALSE);
  556. X    /*
  557. X     *        First of all, find the device
  558. X     */
  559. X    rootnode = (struct RootNode *)DOSBase->dl_Root;
  560. X    dosinfo = (struct DosInfo *)BADDR(rootnode->rn_Info);
  561. X    devnode = (struct DeviceNode *)BADDR(dosinfo->di_DevInfo);
  562. X
  563. X    Forbid();    /* Make sure list doesn't change while we scan it */
  564. X
  565. X    while (devnode != NULL) {
  566. X        p = (unsigned char *)BADDR(devnode->dn_Name)+1;
  567. X        if (!strnicmp(devname, p, namelen-1)) {    /* Don't compare the ':' */
  568. X            /*
  569. X             *        Matched name successfully. Now check if it's a device.
  570. X             *        Note that we carry on searching if it's not a device
  571. X             *        (rather than returning FALSE immediately) since there
  572. X             *        may be a volume called RAD: as well as a device called
  573. X             *        RAD:, for example.
  574. X             */
  575. X            if (devnode->dn_Type == DLT_DEVICE) {
  576. X                if (devnode->dn_Startup < 20)    /* Is there a startup bit?    */
  577. X                    goto notfound;                /* If not, not disk device    */
  578. X                    /* Eek! A GOTO! */
  579. X
  580. X                startup = (struct FileSysStartupMsg *)
  581. X                                        BADDR(devnode->dn_Startup);
  582. X
  583. X                if (dev) {
  584. X                    dev->devname = ((char *)BADDR(startup->fssm_Device))+1;
  585. X                    dev->isfloppy = (!strcmp(TD_NAME, dev->devname));
  586. X                    dev->unit = startup->fssm_Unit;
  587. X                }
  588. X
  589. X                if (startup->fssm_Environ < 20)
  590. X                    goto notfound;
  591. X                /* Another GOTO! The Earth will end in 5 seconds... */
  592. X
  593. X                dosenvec = (struct DosEnvec *)BADDR(startup->fssm_Environ);
  594. X
  595. X                if (dev) {
  596. X                    dev->blocksize        = dosenvec->de_SizeBlock << 2;
  597. X                    dev->blockspertrack    = dosenvec->de_BlocksPerTrack;
  598. X                    dev->surfaces        = dosenvec->de_Surfaces;
  599. X                    dev->lowcyl            = dosenvec->de_LowCyl;
  600. X                    dev->numcyl            = (dosenvec->de_HighCyl -
  601. X                                                dosenvec->de_LowCyl) + 1;
  602. X                }
  603. X                Permit();
  604. X                return (TRUE);
  605. X            }
  606. X        }
  607. X        devnode = (struct DeviceNode *)BADDR(devnode->dn_Next);
  608. X    }
  609. Xnotfound:
  610. X    Permit();
  611. X    return (FALSE);
  612. X}
  613. X
  614. X/*
  615. X *        help()
  616. X *        ------
  617. X *        Prints out a help message about tcopy
  618. X */
  619. Xvoid help()
  620. X{
  621. X    print(
  622. X"Tcopy (C) Copyright Eddy Carroll, January 1990. Freely distributable.\n"
  623. X);
  624. X#ifdef RAMBO
  625. X#define print13(a,b,c,d,e,f,g,h,i,j,k,l,m) (print3(a,b,c),print3(d,e,f),\
  626. X                                    print3(g,h,i),print3(j,k,l),print(m))
  627. Xprint13(
  628. X"Usage: tcopy <flags> <from> <to> <start> <end> <newstart>\n\n",
  629. X"  <flags>     If any of the following are included, then RAD: will be\n",
  630. X"              automatically mounted when tcopy is run:\n\n",
  631. X"              -v<name>    Sets RAD: volume name to be <name> (\"RAMB0\")\n",
  632. X"              -n<name>    Sets RAD: device name to be <name>   (\"RAD\")\n",
  633. X"              -d<name>    Use exec device <name>   (\"ramdrive.device\")\n",
  634. X"              \"-e<txt>\"   Prints <txt> to stdout\n",
  635. X"              -a          Do trackcopy, even if RAD: already mounted\n",
  636. X"              -f#         Sets flags for OpenDevice() to #         (0)\n",
  637. X"              -m#         Sets BufMemType to #                     (1)\n",
  638. X"              -p#         Sets boot priority to #                 (-1)\n",
  639. X"              -t#         Sets number of tracks to #              (10)\n",
  640. X"              -u#         Sets unit number of exec device to #     (0)\n\n"
  641. X);
  642. X#else
  643. X    print("Usage: tcopy <from> <to> <start> <end> <newstart>\n\n");
  644. X#endif RAMBO
  645. X    print("  <from>      Device to copy from (e.g. DF0:)\n");
  646. X    print("  <to>        Device to copy to (e.g. RAD:)\n");
  647. X    print("  <start>     Cylinder to start reading from (e.g. 70)\n");
  648. X    print("  <end>       Cylinder to end reading at (e.g. 79)\n");
  649. X    print("  <newstart>  Cylinder to start writing at (e.g. 0)\n");
  650. X}
  651. X
  652. X
  653. X/*
  654. X *        opendevs()
  655. X *        ----------
  656. X *        Opens the source and destination devices, allocates buffer for
  657. X *        reading and writing etc. Note that if either device is a floppy
  658. X *        drive, the buffer must be allocated in chip memory or trackdisk.device
  659. X *        won't be able to blit into it.
  660. X */
  661. Xvoid opendevs()
  662. X{
  663. X    long memflags = 0;
  664. X
  665. X    if (src->isfloppy || dest->isfloppy)
  666. X        memflags |= MEMF_CHIP;
  667. X
  668. X    cylsize = src->blocksize * src->blockspertrack * src->surfaces;
  669. X    buffer = AllocMem(cylsize, memflags);
  670. X    if (!buffer) {
  671. X        print("Not enough memory for track buffer\n");
  672. X        cleanup(20);
  673. X    }
  674. X
  675. X    reqport = (MSGPORT *)CreatePort(0,0);
  676. X    if (!reqport) {
  677. X        print("Couldn't allocate message port\n");
  678. X        cleanup(20);
  679. X    }
  680. X
  681. X    srcreq    = CreateStdIO(reqport);
  682. X    destreq = CreateStdIO(reqport);
  683. X    if (!srcreq || !destreq) {
  684. X        print("Couldn't allocate IO request - memory is low!\n");
  685. X        cleanup(20);
  686. X    }
  687. X
  688. X    if (OpenDevice(src->devname, src->unit, (IOREQ *)srcreq, 0L)) {
  689. X        print3("Can't open source ", src->devname, "\n");
  690. X        cleanup(20);
  691. X    }
  692. X    srcdevopen = TRUE;
  693. X
  694. X    if (OpenDevice(dest->devname, dest->unit, (IOREQ *)destreq, 0L)) {
  695. X        print3("Can't open destination ", dest->devname, "\n");
  696. X        cleanup(20);
  697. X    }
  698. X    destdevopen = TRUE;
  699. X}
  700. X
  701. X/*
  702. X *        copytracks()
  703. X *        ------------
  704. X *        This is where the actual work gets done. Tracks (cylinders actually)
  705. X *        are copied from start to end on the source device to newstart on
  706. X *        the destination device.
  707. X */
  708. Xvoid copytracks(int start, int end, int newstart)
  709. X{
  710. X    int cyl, retry, numcyls = (end - start) + 1;
  711. X
  712. X    for (cyl = 0; cyl < numcyls; cyl++) {
  713. X        /*
  714. X         *        First read in track from source device
  715. X         */
  716. X        for (retry = 0; retry < 3; retry++) {
  717. X            chkabort();
  718. X            srcreq->io_Command = CMD_READ;
  719. X            srcreq->io_Length  = cylsize;
  720. X            srcreq->io_Offset  = (src->lowcyl + cyl + start) * cylsize;
  721. X            srcreq->io_Data    = buffer;
  722. X            if (!DoIO((IOREQ *)srcreq))
  723. X                break;        /* Succeeded, so break out of loop */
  724. X        }
  725. X        if (retry == 3) {
  726. X            print3("Error reading track ", numtostr(cyl+start)," from disk\n");
  727. X            cleanup(20);
  728. X        }
  729. X
  730. X        /*
  731. X         *        Now write out track to destination device
  732. X         */
  733. X        for (retry = 0; retry < 3; retry++) {
  734. X            chkabort();
  735. X            destreq->io_Command = CMD_WRITE;
  736. X            destreq->io_Length  = cylsize;
  737. X            destreq->io_Offset  = (dest->lowcyl + cyl + newstart) * cylsize;
  738. X            destreq->io_Data    = buffer;
  739. X            if (!DoIO((IOREQ *)destreq))
  740. X                break;        /* Succeeded */
  741. X        }
  742. X        if (retry == 3) {
  743. X            print3("Error writing track ", numtostr(cyl), " to disk\n");
  744. X            cleanup(20);
  745. X        }
  746. X    }
  747. X}
  748. X
  749. X
  750. X/*
  751. X *        SendPacket()
  752. X *        ------------
  753. X *        ``Sort of'' simulates the ARP SendPacket() routine which sends
  754. X *        a packet to AmigaDos, and gets a reply if appropriate. What is
  755. X *        passed in is the action to be executed (one of the ACTION_xxx
  756. X *        definitions in dosextens.h), a pointer to a longword array of 7
  757. X *        arguments to be passed to the device, and the msgport of the device
  758. X *        as returned by DeviceProc("DF0:") for example. If result is non-NULL
  759. X *        then it should be a pointer to a two element array of ULONGs, and it
  760. X *        fills in the 0th element with the primary result, and the the
  761. X *        1st element with the secondary result.
  762. X */
  763. Xint SendPacket(ULONG action, void *args, MSGPORT *devport, ULONG *result)
  764. X{
  765. X    PROC *proc = (PROC *)FindTask(NULL);
  766. X    STDPKT *packet;
  767. X
  768. X    packet = (STDPKT *)AllocMem(sizeof(STDPKT), MEMF_CLEAR | MEMF_PUBLIC);
  769. X    if (!packet)
  770. X        return (FALSE);
  771. X    packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt;
  772. X    packet->sp_Pkt.dp_Link         = &packet->sp_Msg;
  773. X    packet->sp_Pkt.dp_Port         = &proc->pr_MsgPort;
  774. X    packet->sp_Pkt.dp_Type         = action;
  775. X    memcpy(&packet->sp_Pkt.dp_Arg1, args, sizeof(ULONG) * 7);
  776. X
  777. X    /*
  778. X     *        Okay, we've done the necessary magic to create an AmigaDos
  779. X     *        packet lookalike (thanks to Matt Dillon in Transactor V1.1).
  780. X     *        Now we send the message to the Dos process, and get the reply.
  781. X     *        Then our message will be filled in with the response from the
  782. X     *        Dos process.
  783. X     */
  784. X    PutMsg(devport, (struct Message *)packet);
  785. X    WaitPort(&proc->pr_MsgPort);
  786. X    GetMsg(&proc->pr_MsgPort);
  787. X    if (result) {
  788. X        result[0] = packet->sp_Pkt.dp_Res1;
  789. X        result[1] = packet->sp_Pkt.dp_Res2;
  790. X    }
  791. X    FreeMem(packet, sizeof(STDPKT));
  792. X    return (TRUE);
  793. X}
  794. X
  795. X
  796. X
  797. X/*
  798. X *        inhibit()
  799. X *        ---------
  800. X *        This function inhibits (if mode is TRUE) or hibits (if mode is FALSE)
  801. X *        (is hibit the opposite of inhibit? Hmmm...) the specified device.
  802. X */
  803. Xvoid inhibit(MSGPORT *devport, int mode)
  804. X{
  805. X    ULONG pktargs[7];
  806. X    int i;
  807. X
  808. X    pktargs[0] = mode;            /* Select inhibit or opposite */
  809. X    for (i = 1; i < 7; i++)        /* Clear other arguments      */
  810. X        pktargs[i] = 0;
  811. X
  812. X    if (!SendPacket(ACTION_INHIBIT, pktargs, devport, NULL)) {
  813. X        print("Couldn't send inhibit packet to device\n");
  814. X        cleanup(20);
  815. X    }
  816. X}
  817. X
  818. X
  819. X#ifdef RAMBO
  820. X/*
  821. X *        mountramdisk()
  822. X *        --------------
  823. X *        This procedure simply mounts the device specified in the mount
  824. X *        parameter block.
  825. X */
  826. Xint mountramdisk()
  827. X{
  828. X    struct DeviceNode *devnode;
  829. X    long args[7];
  830. X    int i;
  831. X    char *diskname;
  832. X    MSGPORT *devport;
  833. X    static char dosname[200];    /* Temporary storage for dos device name */
  834. X
  835. X    ExpansionBase = (struct ExpansionBase *)
  836. X                        OpenLibrary("expansion.library", 0L);
  837. X    if (!ExpansionBase) {
  838. X        print("Couldn't open expansion.library\n");
  839. X        cleanup(20);
  840. X    }
  841. X
  842. X    devnode = MakeDosNode(&mount);
  843. X    if (!devnode)
  844. X        return (FALSE);
  845. X
  846. X    AddDosNode(bootpri, ADNF_STARTPROC, devnode);
  847. X
  848. X    /*
  849. X     *        Now we've mounted the device, let's try and rename it to
  850. X     *        something different.
  851. X     */
  852. X    strcpy(dosname, mount.dosname);
  853. X    strcat(dosname, ":");
  854. X    devport = (MSGPORT *)DeviceProc(dosname);
  855. X    if (!devport)
  856. X        return (FALSE);
  857. X    for (i = 1; i < 7; i++)
  858. X        args[i] = 0;
  859. X    /*
  860. X     *        Some horrible messing around to make a BSTR
  861. X     */
  862. X    diskname = AllocMem(strlen(volname)+1,MEMF_PUBLIC);
  863. X    strcpy(diskname+1, volname);
  864. X    *diskname = strlen(volname);
  865. X    args[0] = ((long)diskname)>>2;
  866. X    if (!SendPacket(ACTION_RENAME_DISK, args, devport, NULL))
  867. X        print("(Couldn't relabel disk\n");
  868. X    /* Don't return an error, even if SendPacket failed! */
  869. X    FreeMem(diskname, strlen(volname)+1);
  870. X    return (TRUE);
  871. X}
  872. X#endif RAMBO
  873. X
  874. X
  875. X/*
  876. X *        mainline()
  877. X *        ----------
  878. X */
  879. Xvoid main(argc,argv)
  880. Xint argc;
  881. Xchar **argv;
  882. X{
  883. X    unsigned int start, end, newstart;            /* Cylinder numbers */
  884. X
  885. X#ifdef RAMBO
  886. X/************************* Start of RAMBO Stuff ***************************/
  887. X
  888. X    int doload  = FALSE; /* If true, always copy to device even if mounted */
  889. X
  890. X    if (argc > 1 && argv[1][0] == '-') { /* Handle Rambo options */
  891. X        static char tempname[200];
  892. X        while (argc > 1 && argv[1][0] == '-') {
  893. X            char *str = &argv[1][2];        /* Have handy ptr to string    */
  894. X            int num = atoi(str);            /* Have parameter ready        */
  895. X
  896. X            switch (argv[1][1]) {
  897. X
  898. X                case 'v':                /* Set volume name */
  899. X                    volname = str;
  900. X                    break;
  901. X
  902. X                case 'n':                /* Set device name */
  903. X                    /* Strip trailing ':' */
  904. X                    if (LASTCHAR(str) == ':')
  905. X                        LASTCHAR(str) = '\0';
  906. X                    mount.dosname = str;
  907. X                    break;
  908. X
  909. X                case 'd':                /* Set exec device name */
  910. X                    mount.execname = str;
  911. X                    break;
  912. X
  913. X                case 'u':                /* Set device unit number */
  914. X                    mount.unit = num;
  915. X                    break;
  916. X
  917. X                case 'f':                /* Set flags for OpenDevice() */
  918. X                    mount.flags = num;
  919. X                    break;
  920. X
  921. X                case 't':                /* Set number of tracks/cylinders */
  922. X                    mount.highcyl = num - 1;
  923. X                    break;
  924. X
  925. X                case 'm':                /* Set memory type */
  926. X                    mount.bufmemtype = num;
  927. X                    break;
  928. X
  929. X                case 'p':                /* Set boot priority */
  930. X                    bootpri = num;
  931. X                    break;
  932. X
  933. X                case 'e':                /* Echo message to stdout */
  934. X                    print2(&argv[1][2], "\n");
  935. X                    break;
  936. X
  937. X                case 'a':                /* Force loading into RAD: */
  938. X                    doload  = TRUE;
  939. X                    break;
  940. X
  941. X                default:
  942. X                    print3("Unknown switch ", argv[1], "\n");
  943. X                    help();
  944. X                    cleanup(5);
  945. X            }
  946. X            argv++;
  947. X            argc--;
  948. X        }
  949. X
  950. X        /*
  951. X         *        Setup defaults for mount okay. Now see if the device is
  952. X         *        to be mounted. If it is, then try and mount it. If it was
  953. X         *        already mounted, then quit immediately, unless forceload is
  954. X         *        in effect.
  955. X         *
  956. X         *        Else, see are there any files in RAD:. If there are, quit
  957. X         *        immediately (since we are under Kikstart 1.2, and RAD: has
  958. X         *        just recovered itself from memory), unless forceload is
  959. X         *        in effect.
  960. X         */
  961. X        strcpy(tempname, mount.dosname);
  962. X        strcat(tempname, ":");
  963. X        if (!GetVolume(tempname, NULL)) {
  964. X
  965. X            if (!mountramdisk()) {
  966. X                print3("Error: Couldn't mount device ",tempname,"\n");
  967. X                cleanup(20);
  968. X            }
  969. X        }
  970. X        /*
  971. X         *        Scan device and see if there are files on it.
  972. X         *        Do this by seeing if there are any files in
  973. X         *        the directory. If there aren't, then we can
  974. X         *        force the load, otherwise don't force it.
  975. X         */
  976. X        {
  977. X            struct FileInfoBlock *fib;
  978. X            BPTR lock;
  979. X
  980. X            fib = AllocMem(sizeof(struct FileInfoBlock), 0L);
  981. X            if (!fib) {
  982. X                print("Out of memory allocating FileInfoBlock!\n");
  983. X                cleanup(20);
  984. X            }
  985. X            lock = Lock(tempname, ACCESS_READ);
  986. X            if (lock) {
  987. X                if (Examine(lock, fib)) {
  988. X                    if (!ExNext(lock, fib))
  989. X                        doload = TRUE;
  990. X                }
  991. X                UnLock(lock);
  992. X            }
  993. X            FreeMem(fib, sizeof(struct FileInfoBlock));
  994. X        }
  995. X
  996. X        /*
  997. X         *        Now see if after all that, we still want to go
  998. X         *        ahead with the load into RAD:. If not, then just
  999. X         *        exit silently (to let the startup-sequence carry
  1000. X         *        on okay).
  1001. X         */
  1002. X        if (!doload)
  1003. X            cleanup(0);
  1004. X    }
  1005. X
  1006. X/************************* End of RAMBO Stuff ***************************/
  1007. X#endif RAMBO
  1008. X
  1009. X#define NONUM(x) (!isdigit(argv[x][0]))
  1010. X
  1011. X    if (argc != 6 || NONUM(3) || NONUM(4) || NONUM(5)) {
  1012. X        help();
  1013. X        cleanup(5);
  1014. X    }
  1015. X
  1016. X    srcname  = argv[1];
  1017. X    destname = argv[2];
  1018. X    start    = atoi(argv[3]);
  1019. X    end      = atoi(argv[4]);
  1020. X    newstart = atoi(argv[5]);
  1021. X
  1022. X    if (!GetVolume(srcname, src)) {
  1023. X        print2(srcname, " is not a valid disk device\n");
  1024. X        cleanup(20);
  1025. X    }
  1026. X
  1027. X    if (!GetVolume(destname, dest)) {
  1028. X        print2(destname, " is not a valid disk device\n");
  1029. X        cleanup(20);
  1030. X    }
  1031. X
  1032. X#define NOTSAME(x) (src->x != dest->x)
  1033. X
  1034. X    if (NOTSAME(blocksize) || NOTSAME(blockspertrack) || NOTSAME(surfaces)) {
  1035. X        print3(srcname, " and ", destname);
  1036. X        print(" do not have same track sizes\n");
  1037. X        cleanup(20);
  1038. X    }
  1039. X
  1040. X    if (start > end) {
  1041. X        print("Start track is greater than end track.\n");
  1042. X        cleanup(20);
  1043. X    }
  1044. X
  1045. X    if (end >= src->numcyl) {
  1046. X        print3("Maximum end track on ", srcname, " is");
  1047. X        print2(numtostr(src->numcyl - 1), ".\n");
  1048. X        cleanup(20);
  1049. X    }
  1050. X
  1051. X    if ((newstart + (end - start)) >= dest->numcyl) {
  1052. X        print2("There is not room for ", numtostr(1 + end - start));
  1053. X        print3(" tracks on ", destname, "\n");
  1054. X        cleanup(20);
  1055. X    }
  1056. X
  1057. X    destport = (MSGPORT *)DeviceProc(destname);
  1058. X    if (!destport) {
  1059. X        print3("Can't locate process for device ", destname,"\n");
  1060. X        cleanup(20);
  1061. X    }
  1062. X
  1063. X    /*
  1064. X     *        The two devices are valid, so now open the exec devices which
  1065. X     *        they use.
  1066. X     */
  1067. X    opendevs();
  1068. X    inhibit(destport, TRUE);
  1069. X    inhibited = TRUE;
  1070. X    copytracks(start, end, newstart);
  1071. X    cleanup(0);
  1072. X}
  1073. END_OF_FILE
  1074. if test 22873 -ne `wc -c <'src/tcopy.c'`; then
  1075.     echo shar: \"'src/tcopy.c'\" unpacked with wrong size!
  1076. fi
  1077. # end of 'src/tcopy.c'
  1078. fi
  1079. if test -f 'src/tiny.a' -a "${1}" != "-c" ; then 
  1080.   echo shar: Will not clobber existing file \"'src/tiny.a'\"
  1081. else
  1082. echo shar: Extracting \"'src/tiny.a'\" \(6132 characters\)
  1083. sed "s/^X//" >'src/tiny.a' <<'END_OF_FILE'
  1084. X*:ts=8
  1085. X****************************************************************************
  1086. X*                                       *
  1087. X* TINY.A                  (C) Copyright Eddy Carroll 1989  *
  1088. X* ~~~~~~                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
  1089. X*                                       *
  1090. X* Replacement startup code for Lattice C V5.04. Use instead of c.o       *
  1091. X* This has many features stripped out to allow small utilities to have       *
  1092. X* as small a filesize as possible. In particular, don't call any of the    *
  1093. X* stdio functions.                               *
  1094. X*                                       *
  1095. X****************************************************************************
  1096. X
  1097. X    INCLUDE "exec/types.i"
  1098. X    INCLUDE "exec/alerts.i"
  1099. X    INCLUDE "exec/nodes.i"
  1100. X    INCLUDE "exec/lists.i"
  1101. X    INCLUDE "exec/ports.i"
  1102. X    INCLUDE "exec/libraries.i"
  1103. X    INCLUDE "exec/tasks.i"
  1104. X    INCLUDE "libraries/dos.i"
  1105. X    INCLUDE "libraries/dosextens.i"
  1106. X    INCLUDE "workbench/startup.i"
  1107. X    INCLUDE "exec/funcdef.i"
  1108. X    INCLUDE "exec/exec_lib.i"
  1109. X    INCLUDE "libraries/dos_lib.i"
  1110. X
  1111. XMAXARGS        EQU 100    ; Maximum number of command line arguments from CLI
  1112. XAbsExecBase EQU 4    ; Welcome to the only fixed point in the universe
  1113. X
  1114. X* A useful macro to let us call library routines
  1115. Xcallsys macro
  1116. X    CALLLIB _LVO\1
  1117. X    endm
  1118. X
  1119. X    xdef    XCEXIT
  1120. X    xdef    exit
  1121. X    xref    LinkerDB
  1122. X    xref    _BSSBAS
  1123. X    xref    _BSSLEN
  1124. X
  1125. X    csect    text,0,0,1,2        * xref's after this are 16-bit reloc
  1126. X    xref    main            * Name of C program to start with.
  1127. X
  1128. Xstart:
  1129. X    movem.l d1-d6/a0-a6,-(a7)
  1130. XREGSIZE EQU    (6+7)*4
  1131. X    lea    REGSIZE(a7),A5        * Determine old stack pointer
  1132. X    move.l    a0,a2            * Save command pointer
  1133. X    move.l    d0,d2            * and command length
  1134. X    lea    LinkerDB,a4        * Load base register
  1135. X
  1136. X    move.l    AbsExecBase.W,a6
  1137. X    move.l    a6,SysBase(A4)
  1138. X    move.l    a7,_StackPtr(A4)    * Save stack ptr
  1139. X
  1140. X    suba.l    a1,a1
  1141. X    callsys    FindTask        * Find out our task ID
  1142. X    move.l    d0,a3
  1143. X
  1144. X    move.l    a5,D0              * get top of stack
  1145. X    sub.l    4(a5),D0        * compute bottom
  1146. X    add.l    #128,D0         * allow for parms overflow
  1147. X    move.l    D0,_base(A4)        * save for stack checking
  1148. X
  1149. X    lea    DOSName(A4),A1
  1150. X    moveq.l    #0,D0
  1151. X    callsys    OpenLibrary
  1152. X    move.l    D0,DOSBase(A4)
  1153. X    bne    getcom
  1154. XnoDOS:
  1155. X    moveq.l #100,d0
  1156. X    bra    exit2
  1157. X
  1158. X*------ find command name:
  1159. Xgetcom:
  1160. X    move.l  pr_CLI(a3),a0
  1161. X    add.l    a0,a0
  1162. X    add.l    a0,a0
  1163. X    move.l    cli_CommandName(a0),a1
  1164. X    add.l    a1,a1
  1165. X    add.l    a1,a1
  1166. X
  1167. X*------ collect parameters:
  1168. X    move.l    d2,d0            * get command line length
  1169. X    moveq.l #0,d1
  1170. X    move.b    (a1)+,d1
  1171. X    move.l    a1,_ProgramName(A4)
  1172. X    add.l    d1,d0            * add length of command name
  1173. X    addq.l    #1,d0            * allow for space after command
  1174. X
  1175. X    clr.w    -(A7)            * set null terminator for command line
  1176. X    addq.l    #1,D0            * force to even number of bytes
  1177. X    andi.w    #$fffe,D0        * (round up)
  1178. X    sub.l    D0,A7            * make room on stack for command line
  1179. X    subq.l    #2,D0
  1180. X    clr.w    0(A7,D0)
  1181. X
  1182. X*------ copy command line onto stack
  1183. X    move.l    d2,d0            * get command line length
  1184. X    subq.l    #1,d0
  1185. X    add.l    d1,d2
  1186. X
  1187. Xcopy_line:
  1188. X    move.b    0(A2,D0.W),0(A7,D2.W)    * copy command line to stack
  1189. X    subq.l    #1,d2
  1190. X    dbf    d0,copy_line
  1191. X    move.b    #' ',0(a7,d2.w)     * add space between command and parms
  1192. X    subq.l    #1,d2
  1193. X
  1194. Xcopy_cmd:
  1195. X    move.b    0(a1,d2.w),0(a7,d2.w)    * copy command name to stack
  1196. X    dbf    d2,copy_cmd
  1197. X    move.l    a7,a1            * Get pointer to new command line
  1198. X
  1199. X    sub.l    #(MAXARGS*4),a7        * Reserve space for argv[]
  1200. X    move.l    a7,a2            * Initialise base into array
  1201. X    move.l    a2,a3            * Save base of argv
  1202. X    moveq    #0,d2            * Initialise argc
  1203. X
  1204. X*
  1205. X* From here on down, A1 is pointer into command line
  1206. X*
  1207. Xbuild_argv:
  1208. X    bsr.s    getnext            * Read next character from line
  1209. X    bcs.s    doquote            * If quote, handle
  1210. X    beq.s    build_argv        * If white space, skip over it
  1211. X
  1212. X    lea    -1(a1),a0        * Get address of this parameter
  1213. X    bsr.s    bumpargv        * Store it to argv[] array
  1214. Xbuild_2:
  1215. X    bsr.s    getnext            * Get next character
  1216. X    bne.s    build_2            * If not white space, keep looking
  1217. X    clr.b    -1(a1)            * Zero-terminate current argument
  1218. X    bra.s    build_argv        * And go back to get next argument
  1219. X
  1220. Xdoquote:
  1221. X    move.l    a1,a0            * Get pointer to this argument
  1222. X    bsr.s    bumpargv        * Output it to argv[]
  1223. Xquote_2:
  1224. X    bsr.s    getnext            * Get next character
  1225. X    bcc.s    quote_2            * If not quote, keep looking
  1226. X    clr.b    -1(a1)            * Zero-terminate current argument
  1227. Xquote_3:
  1228. X    bsr.s    getnext            * Get next character
  1229. X    bne.s    quote_3            * Skip until space reached
  1230. X    beq.s    build_argv        * Go back and read next argument
  1231. X
  1232. Xbumpargv:
  1233. X    move.l    a0,(a2)+        * Output ptr to current argument
  1234. X    addq    #1,d2            * Increment argc
  1235. X    cmpi    #MAXARGS,d2        * Used up all our arguments yet?
  1236. X    bls.s    qrts            * If not, then return
  1237. X    moveq    #110,d0            * Else set return code
  1238. X    bra.s    exit2            * And exit
  1239. X
  1240. X*
  1241. X* Reads next character from command line. If zero, never returns, but
  1242. X* drops into call to main. Else, returns, with C=1 if character is quote,
  1243. X* Z=1 if character is white space.
  1244. X*
  1245. Xgetnext:
  1246. X    move.b    (a1)+,d0        * Get character from command line
  1247. X    beq.s    get_2            * Exit if end of line
  1248. X    cmp.b    #34,d0            * Check if quote
  1249. X    beq.s    isquote            *
  1250. X    cmp.b    #32,d0            * Check if space
  1251. X    beq.s    isspace            *
  1252. X    cmp.b    #9,d0            * Or tab
  1253. X    beq.s    isspace            *
  1254. X    cmp.b    #10,d0            * Or end of line
  1255. Xisspace:
  1256. X    andi    #$1E,ccr        * Clear carry flag, retaining Z
  1257. Xqrts    rts
  1258. X
  1259. Xisquote:
  1260. X    ori    #1,ccr            * Set carry flag
  1261. X    andi    #$FB,ccr        * Clear zero flag
  1262. X    rts                * And return
  1263. X
  1264. Xget_2:
  1265. X    move.l    a3,-(a7)        * Push argv onto stack
  1266. X    move.l    d2,-(a7)        * Push argc onto stack
  1267. X
  1268. X    lea    _BSSBAS,a3        * get base of BSS
  1269. X    moveq    #0,d1
  1270. X    move.l    #_BSSLEN,d0        * get length of BSS in longwords
  1271. X    bra.s    clr_lp            * and clear for length given
  1272. Xclr_bss move.l    d1,(a3)+
  1273. Xclr_lp    dbf    d0,clr_bss
  1274. X
  1275. Xdomain:
  1276. X    jsr    main(PC)        * Call main(argc,argv)
  1277. X    moveq.l #0,d0            * Set successful status
  1278. X    bra.s    exit2
  1279. X
  1280. Xexit:
  1281. X_exit:
  1282. XXCEXIT:
  1283. X    move.l    4(SP),d0        * Extract return code
  1284. Xexit2:
  1285. X    move.l    d0,-(a7)
  1286. X    move.l    AbsExecBase.W,a6
  1287. X    move.l    DOSBase(A4),a1
  1288. X    callsys CloseLibrary        * Close Dos library
  1289. X
  1290. X*------ this rts sends us back to DOS:
  1291. XexitToDOS:
  1292. X    MOVE.L    (A7)+,D0
  1293. X    movea.l _StackPtr(a4),SP    * Restore stack ptr
  1294. X    movem.l (a7)+,d1-d6/a0-a6
  1295. X    rts
  1296. X
  1297. X*-----------------------------------------------------------------------
  1298. X* Global definitions
  1299. X*
  1300. X    csect    __MERGED,1,,2,2
  1301. X
  1302. X    xdef    NULL,SysBase,LoadAddress,DOSBase
  1303. X    xdef    _oserr,_OSERR,_ONBREAK
  1304. X    xdef    _ProgramName,_StackPtr,_base
  1305. X
  1306. XNULL           dc.l    0
  1307. X_base           dc.l    0
  1308. X_oserr           equ     *
  1309. X_OSERR           dc.l    0
  1310. X_ONBREAK       dc.l    0
  1311. XSysBase        dc.l    0
  1312. XLoadAddress    dc.l    0
  1313. X_StackPtr      dc.l    0
  1314. XDOSBase        dc.l    0
  1315. X_ProgramName   dc.l    0
  1316. XDOSName        dc.b    'dos.library',0
  1317. X
  1318. X    END
  1319. END_OF_FILE
  1320. if test 6132 -ne `wc -c <'src/tiny.a'`; then
  1321.     echo shar: \"'src/tiny.a'\" unpacked with wrong size!
  1322. fi
  1323. # end of 'src/tiny.a'
  1324. fi
  1325. if test -f 'tcopy.doc' -a "${1}" != "-c" ; then 
  1326.   echo shar: Will not clobber existing file \"'tcopy.doc'\"
  1327. else
  1328. echo shar: Extracting \"'tcopy.doc'\" \(10599 characters\)
  1329. sed "s/^X//" >'tcopy.doc' <<'END_OF_FILE'
  1330. X
  1331. X                TCOPY -- copies tracks from one disk to another
  1332. X
  1333. X             (C) Copyright Eddy Carroll 1990. Freely distributable.
  1334. X
  1335. X
  1336. XINTRODUCTION
  1337. X
  1338. X    One of the nicer additions that came with Workbench 1.3 was RAD:, the
  1339. X    recoverable ram disk. A handy feature of RAD: is that it can be made to
  1340. X    look like a floppy disk, and you can then copy an entire disk into it
  1341. X    in one go -- much quicker than copying files in seperately.
  1342. X
  1343. X    Unfortunately, you need to have an 880K RAD: to do this; since I only
  1344. X    have a 2 Meg Amiga, I can't really afford to lose that much memory.
  1345. X    Thus, Tcopy was born.
  1346. X
  1347. X    Tcopy is essentially a DiskCopy command which will copy a specified
  1348. X    range of tracks (actually cylinders, but most people seem to prefer to
  1349. X    call them tracks) from one disk to another. Using Tcopy, you can store
  1350. X    a complete "dump" of RAD: on your startup disk, and then copy it back
  1351. X    into RAD: very rapidly. For example, it takes about 15 seconds to load
  1352. X    up my 275K RAD (as opposed to around 45 seconds when the files were
  1353. X    being copied in one at a time). This is a loading speed of around
  1354. X    18K/second. So much for the Amiga's "slow" floppy drives :-)
  1355. X
  1356. X    To help speed up your startup times even more, Tcopy can automatically
  1357. X    mount RAD: (for all you purists who don't think this sort of thing
  1358. X    belongs in a track copier, tcopy can be readily compiled without the
  1359. X    RAD: handling). If you have just done a reset and RAD: was already in
  1360. X    memory, then Tcopy won't bother reloading it unless you specifically
  1361. X    ask it to.
  1362. X
  1363. X
  1364. XUSAGE
  1365. X
  1366. X    The command template for Tcopy looks like this:
  1367. X
  1368. X        tcopy <options> <from> <to> <start> <end> <newstart>
  1369. X
  1370. X    The <options> are all to do with RAD: and if you don't specify any
  1371. X    of them, Tcopy won't try to mount it. This allows you to use Tcopy for
  1372. X    copying tracks between two normal devices (such as DF0: and DF1:)
  1373. X    without having RAD: confusing things. I'll discuss the valid options
  1374. X    in a little while.
  1375. X
  1376. X    <from> and <to> give the source and destination devices respectively
  1377. X    that Tcopy is to use. These devices can be different sizes, but they
  1378. X    must both have the same track size (i.e. same number of blocks/track
  1379. X    and number of surfaces).
  1380. X
  1381. X    <start> specifies the track to start copying from, <end> specifies
  1382. X    the track to copy up to (and including), and <newstart> specifies
  1383. X    the track to start copying to on the destination device.
  1384. X
  1385. X    For example, supposing you wanted to use Tcopy to copy a disk from
  1386. X    drive 0 to drive 1. You could type
  1387. X
  1388. X        tcopy DF0: DF1: 0 79 0
  1389. X
  1390. X    meaning "copy tracks 0 to 79 on DF0: to track 0 upwards on DF1:".
  1391. X    It should be pointed out however that Tcopy doesn't make a particularly
  1392. X    good disk copier, because:
  1393. X
  1394. X      - It requires that the destination disk already be formatted
  1395. X      - It doesn't verify the data was written properly
  1396. X      - It is about twice as slow as DiskCopy when writing to floppy
  1397. X      - It doesn't update the root block on the destination disk, so
  1398. X        AmigaDOS will see two disks that look identical, and will go
  1399. X        a little bit crazy trying to sort it out.
  1400. X
  1401. X    Hence, it's probably best to keep Tcopy for loading RAD:, and for
  1402. X    copying the odd single track around when needed.
  1403. X
  1404. X
  1405. XOPTIONS
  1406. X
  1407. X    Now onto the options which are supported for mounting RAD:  Any
  1408. X    or all of these options may appear; options which are ommitted get
  1409. X    the default values indicated in brackets. Remember that Tcopy will only
  1410. X    mount RAD: automatically if at least one of the options is specified.
  1411. X    Also, you should have ramdrive.device in your DEVS: directory.
  1412. X
  1413. X    -v<name>     (RAMB0)
  1414. X        Sets the volume name of the mounted device to <name>. This is the
  1415. X        name that appears under the disk icon on Workbench.
  1416. X
  1417. X    -n<name>     (RAD)
  1418. X        Sets the AmigaDOS device name of the mounted device to <name>. This
  1419. X        is the "real" name, which cannot be altered once set.
  1420. X
  1421. X    -e<txt>
  1422. X        Outputs <txt> to the screen. This is useful if you want to display
  1423. X        a message while the copying takes place. If the message contains
  1424. X        any spaces, you will need to surround the entire option with
  1425. X        quotation marks. For example, you might use something like this:
  1426. X
  1427. X            "-eNow copying startup disk to RAD:"
  1428. X
  1429. X    -a
  1430. X        Normally, Tcopy will only actually do the diskcopy into RAD: if it
  1431. X        finds RAD: has no files after it has been mounted (i.e. it is a
  1432. X        cold startup, rather than a reset). The rest of the time, it will
  1433. X        mount RAD: and then quit immediately.
  1434. X
  1435. X        You may occasionally want to override this behaviour. Specifying -a
  1436. X        will tell Tcopy to always copy the disk into RAD: even when it
  1437. X        doesn't think its necessary. This could be useful if you have
  1438. X        several different startup disks, each containing a different set
  1439. X        of files to load into RAD: (one for programming, one for TeX etc.)
  1440. X
  1441. X    -t#          (10)
  1442. X        Sets the number of tracks that RAD: will have, and therefore the
  1443. X        amount of memory it will take up. Each track occupies about 11K
  1444. X        of memory. In general, you will want to customise this to suit
  1445. X        your system rather than leaving it at the default.
  1446. X
  1447. X    -p#          (-1)
  1448. X        Sets the boot priority for RAD:. This is only useful to Kikstart 1.3
  1449. X        users who can boot from RAD: (you 1.2 users don't know what you're
  1450. X        missing!)  The default of -1 means that the Amiga will first try to
  1451. X        boot from a floppy disk in drive 0 and if that fails, will then boot
  1452. X        from RAD. If you set this value to 127, the Amiga will always
  1453. X        boot from RAD: regardless of what's in drive 0.
  1454. X
  1455. X    You are unlikely to ever need to use the following options, but they
  1456. X    are included for the adventurous to play with. They give you control
  1457. X    over several of the fields that normally appear in the mountlist.
  1458. X    Don't mess with them unless you know what you are doing!
  1459. X
  1460. X    -d<name>     (ramdrive.device)
  1461. X        Sets the name of the underlying exec device associated with the
  1462. X        AmigaDos device.
  1463. X
  1464. X    -f#          (0)
  1465. X        Sets the flags to specify when calling OpenDevice().
  1466. X
  1467. X    -m#          (1)
  1468. X        Specifies the type of memory to use; the default is Public Memory
  1469. X        which is basically any memory that happens to be free.
  1470. X
  1471. X
  1472. XCREATING A STARTUP DISK
  1473. X
  1474. X    So, now that you know what Tcopy can do, lets get down to essentials.
  1475. X    Namely, how to put together a disk that boots up as quickly as possible.
  1476. X
  1477. X    My system consists of an A1000 with 1.3 Kikstart, 2 Megs of RAM, and
  1478. X    a C Ltd. hard drive (no autoboot). My RAD: is 275K, and contains
  1479. X    a fairly stripped down Workbench -- essentially just enough to
  1480. X    get the hard drive up and running, and to install my favourite
  1481. X    resident utilities (Dmouse, Conman, BlitzFonts and Snap).
  1482. X
  1483. X    My startup disk looks like this:
  1484. X
  1485. X        Directory of HD_Boot:
  1486. X            c
  1487. X            devs
  1488. X            l
  1489. X            libs
  1490. X            s
  1491. X            Tracks1-25
  1492. X
  1493. X        Directory of HD_Boot:c
  1494. X            RemRad
  1495. X            Tcopy
  1496. X
  1497. X        Directory of HD_Boot:devs
  1498. X            ramdrive.device
  1499. X            system-configuration
  1500. X
  1501. X        Directory of HD_Boot:s
  1502. X            startup-sequence
  1503. X
  1504. X    If you are paying attention, you may have noticed the file Tracks55-79
  1505. X    above. This is a special file created by the Tfile program which
  1506. X    accompanies Tcopy, and to AmigaDos, it looks as if it occupies
  1507. X    tracks 55 to 79 of the disk. This means that I can store my copy of
  1508. X    RAD: on these tracks, without having to worry about AmigaDos trying
  1509. X    to overwrite it if I go to save a new file on the disk.
  1510. X
  1511. X    My startup-sequence looks like this:
  1512. X
  1513. X        c:tcopy -t25 -vRAD "-eBooting up 275K RAD..." df0: rad: 1 25 0
  1514. X        rad:c/cd rad:
  1515. X        rad:c/defdisk rad:
  1516. X        rad:c/execute rad:s/startup-sequence
  1517. X
  1518. X    The first command is the only one that gets loaded in from disk. It
  1519. X    mounts a RAD: with 25 tracks (275K), changes the volume name to RAD:
  1520. X    instead of RAMB0: (which I don't like at all), prints a brief message
  1521. X    and then copies tracks 1 to 25 of the startup disk to RAD:. I have
  1522. X    arranged that RAD: contains enough commands to allow the bootup to
  1523. X    be carried on from there.
  1524. X
  1525. X    The next command changes the current directory to RAD: (mainly because
  1526. X    the execute command lower down will create a temporary file in the
  1527. X    current disk, and I want it to do this in RAD: instead of on my
  1528. X    write-protected boot disk!)  After this, DefDisk does all the necessary
  1529. X    assigns to make RAD: look like the bootup disk (so that I can remove
  1530. X    the real bootup disk for good, and AmigaDos won't ever ask me to
  1531. X    insert it again). DefDisk is a really nice little P.D. program which is
  1532. X    well worth hunting down.
  1533. X
  1534. X    The final step is to execute the real startup-sequence located in RAD:.
  1535. X    This is the same startup-sequence that will get executed when I reset
  1536. X    in future (since I am booting from RAD:).
  1537. X
  1538. X    If I accidentally reset with my boot disk in DF0:, no harm is done;
  1539. X    Tcopy will see that RAD: is already loaded and exit immediately,
  1540. X
  1541. X    If I had Kikstart 1.2 instead of 1.3, the only change I would have to
  1542. X    make would be booting from my startup disk each time I reset rather
  1543. X    than from RAD:. This would still be very fast, since Tcopy will only
  1544. X    copy the disk into RAD: the first time I bootup.
  1545. X
  1546. X    I actually created the startup disk as follows. First of all, I
  1547. X    mounted RAD: manually, and filled it with all the goodies I wanted.
  1548. X    Then I formatted a blank disk, and ran Tfile on it to create the
  1549. X    dummy file Tracks1-25 so that those tracks would remain free to store
  1550. X    the copy of RAD: on. The command I used was:
  1551. X
  1552. X        tfile DF0:Tracks1-25 1 25
  1553. X
  1554. X    Then I copied RAD: to the disk with Tcopy:
  1555. X
  1556. X        tcopy RAD: DF0: 0 24 1
  1557. X
  1558. X    Finally, I created the minimal bootdisk listed earlier by copying over
  1559. X    all the files and directories needed.
  1560. X
  1561. X    The result? It takes just under 25 seconds from a cold reset to load
  1562. X    mount and fill the 275K RAD:, and pass control to its startup-sequence.
  1563. X    While it's not as nice as booting off a hard drive, it makes booting
  1564. X    from floppy a great deal more bearable!
  1565. X
  1566. X
  1567. XRELEASE HISTORY
  1568. X
  1569. X    V1.0
  1570. X        First release, January 1990. No known bugs, but this will
  1571. X        probably change in the future...
  1572. X
  1573. X
  1574. XAUTHOR
  1575. X
  1576. X    Please direct any praise, criticism, general suggestions or
  1577. X    large sums of money to:
  1578. X
  1579. X    Eddy Carroll
  1580. X    ecarroll@vax1.tcd.ie (Trinity College, Dublin, Ireland)
  1581. END_OF_FILE
  1582. if test 10599 -ne `wc -c <'tcopy.doc'`; then
  1583.     echo shar: \"'tcopy.doc'\" unpacked with wrong size!
  1584. fi
  1585. # end of 'tcopy.doc'
  1586. fi
  1587. if test -f 'tfile.doc' -a "${1}" != "-c" ; then 
  1588.   echo shar: Will not clobber existing file \"'tfile.doc'\"
  1589. else
  1590. echo shar: Extracting \"'tfile.doc'\" \(5773 characters\)
  1591. sed "s/^X//" >'tfile.doc' <<'END_OF_FILE'
  1592. X
  1593. X                      TFILE -- reserves tracks on a disk
  1594. X
  1595. X             (C) Copyright Eddy Carroll 1990. Freely distributable.
  1596. X
  1597. X
  1598. XINTRODUCTION
  1599. X
  1600. X    There are occasionally times when you want highspeed access to floppy
  1601. X    disks, and don't want the overhead associated with going through
  1602. X    AmigaDos. One example might be a program to play sound samples
  1603. X    directly from disk (reading in a track's worth of data at a time).
  1604. X    Another example is copying a "minidisk" into RAD: during bootup (see
  1605. X    the documentation for TCOPY for more information on this).
  1606. X
  1607. X    This is fine in theory, but if you go and start using disk tracks for
  1608. X    your own data, sooner or later you're going to overwrite some AmigaDOS
  1609. X    information (or AmigaDOS will overwrite your tracks). What you really
  1610. X    need is a way to tell AmigaDOS not to use the tracks that you are
  1611. X    using.
  1612. X
  1613. X    This is in fact exactly what TFILE does (what a coincidence :-)
  1614. X    It creates a dummy file on a disk that looks to AmigaDOS as if it
  1615. X    contains all the blocks associated with a range of tracks. You can
  1616. X    then happily intermix your private data and standard AmigaDOS files
  1617. X    without any danger of one corrupting the other. For example, if you
  1618. X    have a game that wants direct access to your hard drive, you could
  1619. X    reserve a few cylinders for it to use without having to do a complete
  1620. X    reformat and partition. Similarly for something like AMax.
  1621. X
  1622. X
  1623. XUSAGE
  1624. X
  1625. X    The command template for Tfile looks like this:
  1626. X
  1627. X        tfile <pathname> <start> <end>
  1628. X
  1629. X    <pathname> is the full AmigaDOS pathname of the file you want to
  1630. X    create which will reserve the tracks. You must specify a disk device
  1631. X    (such as DF0:) rather than a volume name. You may like to stick the
  1632. X    file out of the way in the Devs directory or some such place, called
  1633. X    something like TracksX-Y.
  1634. X
  1635. X    <start> and <end> specify the range of tracks to be reserved. When
  1636. X    you run Tfile, these tracks must not be in use by AmigaDOS or Tfile
  1637. X    will complain. Hence, it's a good idea to run Tfile shortly after you
  1638. X    have just formatted a disk, and only then copy over any AmigaDOS files
  1639. X    you want to use (AmigaDOS will arrange them nicely around your reserved
  1640. X    tracks). Obviously, <start> must be less than <end>, and neither can
  1641. X    exceed the number of tracks available on the disk. Tracks are numbered
  1642. X    from 0 upwards, so the 80 tracks on DF0: are numbered 0 to 79.
  1643. X
  1644. X    AmigaDOS usually reserves a few blocks at the start of a disk for
  1645. X    private information. The bootblock on floppy disks is a good example
  1646. X    of this. If the track range you specify includes these reserved blocks,
  1647. X    Tfile will print a warning message. You can safely ignore this -- it is
  1648. X    just there to remind you that you need to be careful writing to the
  1649. X    tracks you specified so as not to overwrite important information.
  1650. X
  1651. X    To make things clearer, a quick example might be useful. Lets suppose
  1652. X    you want to reserve the last 10 tracks on a floppy disk for some
  1653. X    reason (tracks 70 to 79). Just put the disk in DF0: and say
  1654. X
  1655. X        tfile df0:Tracks70-79 70 79
  1656. X
  1657. X    and after a few moments of disk access, you will find yourself with
  1658. X    a new file which is 107848 bytes in size, and a correspondingly
  1659. X    smaller amount of room on the disk.
  1660. X
  1661. X
  1662. XADDITIONAL NOTES
  1663. X
  1664. X    Tfile will work with both the old filing system and fast filing system.
  1665. X    On the OFS, if you try to display the dummy file, you will see a brief
  1666. X    message telling you that it isn't a real file, and describing which
  1667. X    tracks it reserves. You will not be able to access anything other
  1668. X    than the message, and it's not a good idea to try and fool AmigaDOS
  1669. X    into letting you.
  1670. X
  1671. X    On the FFS, you will see the same message, but shortly after that will
  1672. X    come the actual raw track data itself. This is due to the different
  1673. X    ways the OFS and FFS store the data blocks of a file. If you have a
  1674. X    file editor such as NewZap, you can even edit the disk blocks directly;
  1675. X    with the exception of the initial "message" block, the blocks are
  1676. X    arranged in sequence from the start to end track.
  1677. X
  1678. X    You can have several different portions of the disk reserved if you
  1679. X    like (you might want to reserve almost all of the disk except for a
  1680. X    little bit in the middle for the AmigaDOS root block).
  1681. X
  1682. X    When you are finished using the tracks, you can release the blocks
  1683. X    back to AmigaDOS by deleting the dummy file.
  1684. X
  1685. X    You may occasionally have trouble finding free room on a disk. David
  1686. X    Gay has written a nice pair of programs which display disk fragmentation
  1687. X    and free blocks. These can be found on Fish Disk 278
  1688. X    under the collective title `frag'.
  1689. X
  1690. X
  1691. XFUTURE ADDITIONS
  1692. X
  1693. X    One thing I would like to add is the ability to read in a list of
  1694. X    block numbers from a file and reserve those blocks listed, rather
  1695. X    than being restricted to complete tracks. You could then use Tfile
  1696. X    to map out bad blocks on hard drives, in conjunction with some
  1697. X    program that would actually find such blocks for you. As it is,
  1698. X    you could use Tfile to map out bad tracks on AmigaDOS floppies,
  1699. X    but given the cost of blank disks these days and the chances of
  1700. X    a disk with one bad track developing others, it's not really
  1701. X    a sensible gamble.
  1702. X
  1703. X    To add block lists would not be too difficult given the current
  1704. X    implementation; the only thing needed is time. Unfortunately, I don't
  1705. X    have very much of that at the moment, so don't expect them any time soon.
  1706. X
  1707. X
  1708. XRELEASE HISTORY
  1709. X
  1710. X    V1.0
  1711. X        First release, January 1990. No known bugs, as yet.
  1712. X
  1713. X
  1714. XAUTHOR
  1715. X
  1716. X    Please direct any praise, criticism, general suggestions or
  1717. X    large sums of money to:
  1718. X
  1719. X    Eddy Carroll
  1720. X    ecarroll@vax1.tcd.ie (Trinity College, Dublin, Ireland)
  1721. END_OF_FILE
  1722. if test 5773 -ne `wc -c <'tfile.doc'`; then
  1723.     echo shar: \"'tfile.doc'\" unpacked with wrong size!
  1724. fi
  1725. # end of 'tfile.doc'
  1726. fi
  1727. echo shar: End of archive 1 \(of 2\).
  1728. cp /dev/null ark1isdone
  1729. MISSING=""
  1730. for I in 1 2 ; do
  1731.     if test ! -f ark${I}isdone ; then
  1732.     MISSING="${MISSING} ${I}"
  1733.     fi
  1734. done
  1735. if test "${MISSING}" = "" ; then
  1736.     echo You have unpacked both archives.
  1737.     rm -f ark[1-9]isdone
  1738. else
  1739.     echo You still need to unpack the following archives:
  1740.     echo "        " ${MISSING}
  1741. fi
  1742. ##  End of shell archive.
  1743. exit 0
  1744. -- 
  1745. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  1746.     amiga@cs.odu.edu    
  1747. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  1748. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  1749.  
  1750. Comments, questions, and suggestions s should be addressed to ``amiga-request''
  1751. (only use ``amiga'' for submissions) at the above addresses.
  1752.